package com.example.project7

import android.Manifest
import android.content.ComponentName
import android.content.ContentUris
import android.content.Context
import android.content.Intent
import android.content.ServiceConnection
import android.content.pm.PackageManager
import android.net.Uri
import android.os.Build
import android.os.Bundle
import android.os.IBinder
import android.provider.MediaStore
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge
import androidx.activity.result.contract.ActivityResultContracts
import androidx.annotation.RequiresApi
import androidx.compose.foundation.background
import androidx.compose.foundation.border
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.itemsIndexed
import androidx.compose.material3.Button
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.Card
import androidx.compose.material3.CardDefaults
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Slider
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.MutableState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableIntStateOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.core.content.ContextCompat
import com.example.project7.ui.theme.Project7Theme
import kotlinx.coroutines.delay
import com.example.project7.R
import java.io.File
import java.io.FileOutputStream
import java.io.IOException
import java.util.Locale

class MainActivity : ComponentActivity() {

    private var musicBinder: MusicService.MusicBinder? = null
    private var isBound = false
    private val permissionGrantedState = mutableStateOf(false)

    private val connection = object : ServiceConnection {
        override fun onServiceConnected(name: ComponentName?, service: IBinder?) {
            musicBinder = service as? MusicService.MusicBinder
            isBound = true
        }

        override fun onServiceDisconnected(name: ComponentName?) {
            isBound = false
            musicBinder = null
        }
    }

    private val requestPermission = registerForActivityResult(
        ActivityResultContracts.RequestMultiplePermissions()
    ) { _ ->
        permissionGrantedState.value = hasReadAudioPermission()
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        enableEdgeToEdge()
        permissionGrantedState.value = hasReadAudioPermission()
        setContent {
            Project7Theme {
                Scaffold(modifier = Modifier.fillMaxSize()) { innerPadding ->
                    PlayerScreen(
                        modifier = Modifier.padding(innerPadding),
                        context = this,
                        binderProvider = { musicBinder },
                        requestPermissions = { ensureRuntimePermissions() },
                        permissionsGranted = permissionGrantedState.value
                    )
                }
            }
        }
    }

    override fun onStart() {
        super.onStart()
        val intent = Intent(this, MusicService::class.java)
        ContextCompat.startForegroundService(this, intent)
        bindService(intent, connection, Context.BIND_AUTO_CREATE)
    }

    override fun onStop() {
        super.onStop()
        if (isBound) {
            unbindService(connection)
            isBound = false
        }
    }

    private fun ensureRuntimePermissions() {
        val needs = mutableListOf<String>()
        if (Build.VERSION.SDK_INT >= 33) {
            if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_MEDIA_AUDIO)
                != PackageManager.PERMISSION_GRANTED
            ) needs += Manifest.permission.READ_MEDIA_AUDIO
            // 通知权限用于显示播放通知
            if (ContextCompat.checkSelfPermission(this, Manifest.permission.POST_NOTIFICATIONS)
                != PackageManager.PERMISSION_GRANTED
            ) needs += Manifest.permission.POST_NOTIFICATIONS
        } else {
            if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE)
                != PackageManager.PERMISSION_GRANTED
            ) needs += Manifest.permission.READ_EXTERNAL_STORAGE
        }
        if (needs.isNotEmpty()) {
            requestPermission.launch(needs.toTypedArray())
        } else {
            permissionGrantedState.value = hasReadAudioPermission()
        }
    }

    private fun hasReadAudioPermission(): Boolean {
        return if (Build.VERSION.SDK_INT >= 33) {
            ContextCompat.checkSelfPermission(
                this,
                Manifest.permission.READ_MEDIA_AUDIO
            ) == PackageManager.PERMISSION_GRANTED
        } else {
            ContextCompat.checkSelfPermission(
                this,
                Manifest.permission.READ_EXTERNAL_STORAGE
            ) == PackageManager.PERMISSION_GRANTED
        }
    }
}

private data class UiTrack(
    val uri: Uri,
    val title: String
)

@Composable
private fun PlayerScreen(
    modifier: Modifier,
    context: Context,
    binderProvider: () -> MusicService.MusicBinder?,
    requestPermissions: () -> Unit,
    permissionsGranted: Boolean
) {
    var tracks by remember { mutableStateOf(listOf<UiTrack>()) }
    var currentIndex by remember { mutableIntStateOf(0) }
    var isPlaying by remember { mutableStateOf(false) }
    var duration by remember { mutableIntStateOf(0) }
    var position by remember { mutableIntStateOf(0) }
    var sliderValue by remember { mutableStateOf(0f) }
    var currentTitle by remember { mutableStateOf("") }
    var isUserSeeking by remember { mutableStateOf(false) }

    LaunchedEffect(Unit) {
        requestPermissions()
    }

    LaunchedEffect(permissionsGranted) {
        val mediaStoreTracks = if (permissionsGranted) queryAudio(context) else emptyList()
        val bundledTracks = fallbackTracks(context)
        tracks = (mediaStoreTracks + bundledTracks).distinctBy { it.uri }
    }

    // 轮询播放进度（多线程/协程刷新 UI）
    LaunchedEffect(binderProvider()) {
        while (true) {
            val binder = binderProvider()
            if (binder != null) {
                isPlaying = binder.isPlaying()
                duration = binder.getDuration()
                position = binder.getCurrentPosition()
                val binderIndex = binder.getCurrentIndex()
                if (binderIndex in tracks.indices) {
                    currentIndex = binderIndex
                }
                currentTitle = binder.getCurrentTitle()
            }
            delay(500)
        }
    }

    val titleToShow = when {
        currentTitle.isNotBlank() -> currentTitle
        else -> tracks.getOrNull(currentIndex)?.title ?: ""
    }

    val colorScheme = MaterialTheme.colorScheme
    val gradient = remember(colorScheme) {
        Brush.verticalGradient(
            colors = listOf(
                colorScheme.primary.copy(alpha = 0.18f),
                colorScheme.surface
            )
        )
    }

    Column(
        modifier = modifier
            .fillMaxSize()
            .background(gradient)
            .padding(horizontal = 20.dp, vertical = 16.dp)
    ) {
        Text(
            "本地音乐",
            style = MaterialTheme.typography.headlineSmall,
            color = MaterialTheme.colorScheme.onSurface
        )
        Spacer(Modifier.height(12.dp))

        Card(
            modifier = Modifier.fillMaxWidth(),
            shape = RoundedCornerShape(28.dp),
            colors = CardDefaults.cardColors(
                containerColor = MaterialTheme.colorScheme.surface.copy(alpha = 0.92f)
            ),
            elevation = CardDefaults.cardElevation(defaultElevation = 6.dp)
        ) {
            Row(
                modifier = Modifier
                    .fillMaxWidth()
                    .padding(20.dp),
                verticalAlignment = Alignment.CenterVertically,
                horizontalArrangement = Arrangement.spacedBy(16.dp)
            ) {
                Box(
                    modifier = Modifier
                        .size(72.dp)
                        .clip(shape = CircleShape)
                        .background(MaterialTheme.colorScheme.primaryContainer),
                    contentAlignment = Alignment.Center
                ) {
                    Text(
                        text = "♪",
                        style = MaterialTheme.typography.headlineMedium,
                        color = MaterialTheme.colorScheme.primary
                    )
                }
                Column(
                    verticalArrangement = Arrangement.spacedBy(6.dp),
                    modifier = Modifier.weight(1f)
                ) {
                    Text(
                        text = if (titleToShow.isNotBlank()) titleToShow else "请选择歌曲",
                        style = MaterialTheme.typography.titleLarge
                    )
                    Text(
                        text = if (isPlaying) "正在播放" else "已暂停",
                        style = MaterialTheme.typography.bodyMedium,
                        color = if (isPlaying) MaterialTheme.colorScheme.primary else MaterialTheme.colorScheme.onSurfaceVariant
                    )
                }
            }
        }

        Spacer(Modifier.height(16.dp))

        Text(
            text = "播放列表",
            style = MaterialTheme.typography.titleMedium,
            color = MaterialTheme.colorScheme.onSurfaceVariant
        )

        Spacer(Modifier.height(8.dp))

        Card(
            modifier = Modifier
                .fillMaxWidth()
                .weight(1f),
            colors = CardDefaults.cardColors(
                containerColor = MaterialTheme.colorScheme.surface.copy(alpha = 0.85f)
            ),
            shape = RoundedCornerShape(24.dp)
        ) {
            if (tracks.isEmpty()) {
                Box(
                    modifier = Modifier
                        .fillMaxSize()
                        .padding(24.dp),
                    contentAlignment = Alignment.Center
                ) {
                    Text("未找到本地音乐，请检查媒体库或拷贝到设备")
                }
            } else {
                LazyColumn(
                    modifier = Modifier
                        .fillMaxSize()
                        .padding(12.dp),
                    verticalArrangement = Arrangement.spacedBy(12.dp)
                ) {
                    itemsIndexed(tracks) { index, item ->
                        val isSelected = index == currentIndex
                        Surface(
                            modifier = Modifier
                                .fillMaxWidth()
                                .clip(RoundedCornerShape(18.dp))
                                .border(
                                    width = if (isSelected) 1.5.dp else 0.dp,
                                    color = if (isSelected) MaterialTheme.colorScheme.primary else Color.Transparent,
                                    shape = RoundedCornerShape(18.dp)
                                )
                                .clickable {
                                    val binder = binderProvider() ?: return@clickable
                                    currentIndex = index
                                    binder.setPlaylist(
                                        tracks.map { MusicService.Track(it.uri, it.title) },
                                        index
                                    )
                                },
                            color = if (isSelected) MaterialTheme.colorScheme.primaryContainer else MaterialTheme.colorScheme.surface,
                            tonalElevation = if (isSelected) 3.dp else 0.dp
                        ) {
                            Row(
                                modifier = Modifier
                                    .fillMaxWidth()
                                    .padding(horizontal = 16.dp, vertical = 14.dp),
                                verticalAlignment = Alignment.CenterVertically
                            ) {
                                Column(
                                    modifier = Modifier.weight(1f),
                                    verticalArrangement = Arrangement.spacedBy(4.dp)
                                ) {
                                    Text(
                                        item.title,
                                        style = MaterialTheme.typography.titleMedium,
                                        color = if (isSelected) MaterialTheme.colorScheme.onPrimaryContainer else MaterialTheme.colorScheme.onSurface
                                    )
                                    if (isSelected && isPlaying) {
                                        Text(
                                            "播放中",
                                            style = MaterialTheme.typography.bodySmall,
                                            color = MaterialTheme.colorScheme.primary
                                        )
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }

        Spacer(Modifier.height(20.dp))

        if (titleToShow.isNotBlank()) {
            Text(
                text = titleToShow,
                style = MaterialTheme.typography.titleMedium,
                color = MaterialTheme.colorScheme.onSurface
            )
        }

        Spacer(Modifier.height(8.dp))

        LaunchedEffect(position, duration, isPlaying) {
            if (!isUserSeeking && duration > 0) {
                sliderValue = (position.coerceAtLeast(0).toFloat() / duration).coerceIn(0f, 1f)
            } else if (!isUserSeeking && duration == 0) {
                sliderValue = 0f
            }
        }

        Column {
            Slider(
                value = sliderValue.coerceIn(0f, 1f),
                onValueChange = { v ->
                    isUserSeeking = true
                    sliderValue = v.coerceIn(0f, 1f)
                },
                onValueChangeFinished = {
                    val binder = binderProvider() ?: return@Slider
                    if (duration > 0) {
                        val newPos = (duration * sliderValue).toInt()
                        binder.seekTo(newPos)
                    }
                    isUserSeeking = false
                }
            )
            Row(
                modifier = Modifier.fillMaxWidth(),
                horizontalArrangement = Arrangement.SpaceBetween
            ) {
                Text(formatTime(position), style = MaterialTheme.typography.bodySmall)
                Text(formatTime(duration), style = MaterialTheme.typography.bodySmall)
            }
        }

        Spacer(Modifier.height(16.dp))

        val buttonColors = ButtonDefaults.buttonColors(
            containerColor = MaterialTheme.colorScheme.primary,
            contentColor = MaterialTheme.colorScheme.onPrimary
        )

        Row(
            modifier = Modifier.fillMaxWidth(),
            horizontalArrangement = Arrangement.spacedBy(12.dp)
        ) {
            Button(
                onClick = { binderProvider()?.previous() },
                modifier = Modifier
                    .weight(1f)
                    .height(48.dp),
                colors = buttonColors,
                shape = RoundedCornerShape(24.dp),
                contentPadding = PaddingValues(vertical = 8.dp)
            ) {
                Text(
                    text = "上一首",
                    maxLines = 1,
                    softWrap = false,
                    style = MaterialTheme.typography.labelLarge
                )
            }

            Button(
                onClick = {
                    val binder = binderProvider() ?: return@Button
                    if (isPlaying) {
                        binder.pause()
                    } else {
                        if (binder.getPlaylist().isEmpty() && tracks.isNotEmpty()) {
                            binder.setPlaylist(
                                tracks.map { MusicService.Track(it.uri, it.title) },
                                currentIndex
                            )
                        } else {
                            binder.play()
                        }
                    }
                },
                modifier = Modifier
                    .weight(1f)
                    .height(48.dp),
                colors = buttonColors,
                shape = RoundedCornerShape(24.dp),
                contentPadding = PaddingValues(vertical = 8.dp)
            ) {
                Text(
                    text = if (isPlaying) "暂停" else "播放",
                    maxLines = 1,
                    softWrap = false,
                    style = MaterialTheme.typography.labelLarge
                )
            }

            Button(
                onClick = { binderProvider()?.stopPlayback() },
                modifier = Modifier
                    .weight(1f)
                    .height(48.dp),
                colors = buttonColors,
                shape = RoundedCornerShape(24.dp),
                contentPadding = PaddingValues(vertical = 8.dp)
            ) {
                Text(
                    text = "停止",
                    maxLines = 1,
                    softWrap = false,
                    style = MaterialTheme.typography.labelLarge
                )
            }

            Button(
                onClick = { binderProvider()?.next() },
                modifier = Modifier
                    .weight(1f)
                    .height(48.dp),
                colors = buttonColors,
                shape = RoundedCornerShape(24.dp),
                contentPadding = PaddingValues(vertical = 8.dp)
            ) {
                Text(
                    text = "下一首",
                    maxLines = 1,
                    softWrap = false,
                    style = MaterialTheme.typography.labelLarge
                )
            }
        }
    }
}

private fun queryAudio(context: Context): List<UiTrack> {
    val list = mutableListOf<UiTrack>()
    val collection = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
        MediaStore.Audio.Media.getContentUri(MediaStore.VOLUME_EXTERNAL)
    } else {
        MediaStore.Audio.Media.EXTERNAL_CONTENT_URI
    }
    val projection = arrayOf(
        MediaStore.Audio.Media._ID,
        MediaStore.Audio.Media.TITLE
    )
    val selection = "${MediaStore.Audio.Media.IS_MUSIC} != 0"
    context.contentResolver.query(
        collection,
        projection,
        selection,
        null,
        "${MediaStore.Audio.Media.DATE_ADDED} DESC"
    )?.use { cursor ->
        val idIdx = cursor.getColumnIndexOrThrow(MediaStore.Audio.Media._ID)
        val titleIdx = cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.TITLE)
        while (cursor.moveToNext()) {
            val id = cursor.getLong(idIdx)
            val title = cursor.getString(titleIdx) ?: "未知歌曲"
            val contentUri = ContentUris.withAppendedId(collection, id)
            list += UiTrack(contentUri, title)
        }
    }
    return list
}

private fun fallbackTracks(context: Context): List<UiTrack> {
    val rawTracks = listOf(
        RawAudio(R.raw.qinghuaci, "Qing Hua Ci"),
        RawAudio(R.raw.qingtian, "Qing Tian")
    )
    return rawTracks.mapNotNull { raw ->
        val entryName = context.resources.getResourceEntryName(raw.resId)
        val fileName = "$entryName.mp3"
        val targetFile = File(context.filesDir, fileName)
        if (!targetFile.exists()) {
            try {
                context.resources.openRawResource(raw.resId).use { input ->
                    FileOutputStream(targetFile).use { output ->
                        input.copyTo(output)
                    }
                }
            } catch (io: IOException) {
                io.printStackTrace()
                return@mapNotNull null
            }
        }
        if (!targetFile.exists()) return@mapNotNull null
        UiTrack(
            uri = Uri.fromFile(targetFile),
            title = raw.displayName ?: entryName.replace('_', ' ')
        )
    }
}

private data class RawAudio(val resId: Int, val displayName: String?)

private fun formatTime(milliseconds: Int): String {
    if (milliseconds <= 0) return "00:00"
    val totalSeconds = milliseconds / 1000
    val minutes = totalSeconds / 60
    val seconds = totalSeconds % 60
    return String.format(Locale.getDefault(), "%02d:%02d", minutes, seconds)
}
